using NFreeMarker.Template;

namespace NFreeMarker.Core
{
    /// <summary>
    /// The dot operator. Used to reference items inside a <see cref="ITemplateHashModel"/>.
    /// </summary>
    internal sealed class Dot : Expression
    {
        private readonly Expression _target;
        private readonly string _key;

        internal Dot(Expression target, string key)
        {
            _target = target;
            _key = key;
        }

        protected override ITemplateModel _getAsTemplateModel(Environment env)
        {
            ITemplateModel leftModel = _target.GetAsTemplateModel(env);
            if (leftModel is ITemplateHashModel)
            {
                return ((ITemplateHashModel) leftModel).Get(_key);
            }
            throw InvalidTypeException(leftModel, _target, env, "hash");
        }

        public override string GetCanonicalForm()
        {
            return _target.GetCanonicalForm() + "." + _key;
        }

        internal override bool IsLiteral()
        {
            return _target.IsLiteral();
        }

        protected override Expression DeepCloneImpl(string name, Expression subst)
        {
            return new Dot(_target.DeepClone(name, subst), _key);
        }

        internal bool OnlyHasIdentifiers()
        {
            return (_target is Identifier) || ((_target is Dot) && ((Dot) _target).OnlyHasIdentifiers());
        }
    }
}